/* 
 * File:   BulletSimulator.h
 * Author: jcrada
 *
 * Created on October 3, 2008, 9:55 PM
 */

#ifndef _BULLETSIMULATOR_H
#define	_BULLETSIMULATOR_H
#include "Creature.h"

#include <QtCore/QThread>
#include <btBulletCollisionCommon.h>
#include <btBulletDynamicsCommon.h>
#include <QtCore/QTimer>
#include <QtGui/QApplication>
#include <QtCore/QReadWriteLock>


namespace jcrada {
    class Creature;

    class BulletSimulator {
    private:
        static BulletSimulator* _singleton;

        BulletSimulator();
        virtual ~BulletSimulator();

        btBroadphaseInterface *_broadphase;
        btCollisionConfiguration *_collision_configuration;
        btCollisionDispatcher *_collision_dispatcher;
        btSequentialImpulseConstraintSolver *_constraint_solver;
        btDiscreteDynamicsWorld *_world;
        btCollisionShape *_ground_shape;
        btMotionState *_ground_motion_state;
        btRigidBody *_ground_rigid_body;
        double _min_xyz[3];
        double _max_xyz[3];
        int _max_proxies;
        int _timesteps_per_second;
        Creature* _current_creature;
        QReadWriteLock* _lock;
        volatile bool _hit_the_ground;
        double _gravity;
        int _seconds_for_stabilization;

    public:
        static int main(int argc, char ** argv);
        static bool customContactAddedCallback(btManifoldPoint& cp,
                const btCollisionObject* colObj0, int partId0, int index0,
                const btCollisionObject* colObj1, int partId1, int index1);

        static BulletSimulator& getSingleton() {
            if (!_singleton) {
                _singleton = new BulletSimulator();
                _singleton->initPhysics();
            }
            return *_singleton;
        }

        static void destroySingleton() {
            delete _singleton;
        }

        virtual void step();
        virtual void initPhysics();
        virtual void reset();
        virtual void destroyPhysics();

        virtual void addCreature(Creature& creature);
        virtual void removeCreature();
        virtual void setHitTheGround(bool hit);
        virtual void setGravity(double gravity);

        virtual Creature* currentCreature() const {
            return _current_creature;
        }

        virtual QReadWriteLock& getLock() const {
            return *this->_lock;
        }

        btDiscreteDynamicsWorld& getWorld() const {
            return *_world;
        }

        virtual bool hasHitTheGround() const {
            return this->_hit_the_ground;
        }

        virtual void setTimestepsPerSecond(int tps) {
            this->_timesteps_per_second = tps;
        }

        virtual int getTimestepsPerSecond() const {
            return this->_timesteps_per_second;
        }

        virtual void setMaxProxies(int max_proxies) {
            this->_max_proxies = max_proxies;
        }

        virtual int getMaxProxies() const {
            return this->_max_proxies;
        }

        virtual double getGravity() const {
            return this->_gravity;
        }

    };

}
#endif	/* _BULLETSIMULATOR_H */

